home *** CD-ROM | disk | FTP | other *** search
/ Light ROM 1 / LIGHT-ROM 1 (Amiga Library Services)(1994).iso / ffdisks / d927.lha / Ftp / src / glob.c < prev    next >
C/C++ Source or Header  |  1993-10-07  |  10KB  |  663 lines

  1. /*
  2.  * Copyright (c) 1980 Regents of the University of California.
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms are permitted
  6.  * provided that the above copyright notice and this paragraph are
  7.  * duplicated in all such forms and that any documentation,
  8.  * advertising materials, and other materials related to such
  9.  * distribution and use acknowledge that the software was developed
  10.  * by the University of California, Berkeley.  The name of the
  11.  * University may not be used to endorse or promote products derived
  12.  * from this software without specific prior written permission.
  13.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  14.  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  15.  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  16.  */
  17.  
  18. #ifndef lint
  19. static char sccsid[] = "@(#)glob.c    5.7 (Berkeley) 12/14/88";
  20. #endif /* not lint */
  21.  
  22. /*
  23.  * C-shell glob for random programs.
  24.  */
  25.  
  26. #include <sys/param.h>
  27. #ifdef AMI_TCP
  28. #define NCARGS 32
  29. #endif
  30. #include <sys/stat.h>
  31. //#include <sys/dir.h>
  32. #ifdef AMI_TCP
  33. #include <bsdsocket.h>
  34. #else
  35. #include <ss/socket.h>
  36. #endif
  37.  
  38. #include <stdio.h>
  39. #include <errno.h>
  40. #ifndef AMI_TCP
  41. #include <pwd.h>
  42. #endif
  43.  
  44. #define    QUOTE 0200
  45. #define    TRIM 0177
  46. #define    eq(a,b)        (strcmp(a, b)==0)
  47. #define    GAVSIZ        (NCARGS/6)
  48. #define    isdir(d)    ((d.st_mode & S_IFMT) == S_IFDIR)
  49.  
  50. static    char **gargv;        /* Pointer to the (stack) arglist */
  51. static    int gargc;        /* Number args in gargv */
  52. static    int gnleft;
  53. static    short gflag;
  54. static    int tglob();
  55. char    **glob();
  56. char    *globerr;
  57. char    *home;
  58. struct    passwd *getpwnam();
  59. extern    int errno;
  60. static    char *strspl(), *strend();
  61. char    *malloc();
  62. char    **copyblk();
  63.  
  64. static    int globcnt;
  65.  
  66. char    *globchars = "`{[*?";
  67.  
  68. static    char *gpath, *gpathp, *lastgpathp;
  69. static    int globbed;
  70. static    char *entp;
  71. static    char **sortbas;
  72.  
  73. char **
  74. glob(v)
  75.     register char *v;
  76. {
  77.     char agpath[BUFSIZ];
  78.     char *agargv[GAVSIZ];
  79.     char *vv[2];
  80.     vv[0] = v;
  81.     vv[1] = 0;
  82.     gflag = 0;
  83.     rscan(vv, tglob);
  84.     if (gflag == 0)
  85.         return (copyblk(vv));
  86.  
  87.     globerr = 0;
  88.     gpath = agpath; gpathp = gpath; *gpathp = 0;
  89.     lastgpathp = &gpath[sizeof agpath - 2];
  90.     ginit(agargv); globcnt = 0;
  91.     collect(v);
  92.     if (globcnt == 0 && (gflag&1)) {
  93.         blkfree(gargv), gargv = 0;
  94.         return (0);
  95.     } else
  96.         return (gargv = copyblk(gargv));
  97. }
  98.  
  99. static
  100. ginit(agargv)
  101.     char **agargv;
  102. {
  103.  
  104.     agargv[0] = 0; gargv = agargv; sortbas = agargv; gargc = 0;
  105.     gnleft = NCARGS - 4;
  106. }
  107.  
  108. static
  109. collect(as)
  110.     register char *as;
  111. {
  112.     if (eq(as, "{") || eq(as, "{}")) {
  113.         Gcat(as, "");
  114.         sort();
  115.     } else
  116.         acollect(as);
  117. }
  118.  
  119. static
  120. acollect(as)
  121.     register char *as;
  122. {
  123.     register int ogargc = gargc;
  124.  
  125.     gpathp = gpath; *gpathp = 0; globbed = 0;
  126.     expand(as);
  127.     if (gargc != ogargc)
  128.         sort();
  129. }
  130.  
  131. static
  132. sort()
  133. {
  134.     register char **p1, **p2, *c;
  135.     char **Gvp = &gargv[gargc];
  136.  
  137.     p1 = sortbas;
  138.     while (p1 < Gvp-1) {
  139.         p2 = p1;
  140.         while (++p2 < Gvp)
  141.             if (strcmp(*p1, *p2) > 0)
  142.                 c = *p1, *p1 = *p2, *p2 = c;
  143.         p1++;
  144.     }
  145.     sortbas = Gvp;
  146. }
  147.  
  148. static
  149. expand(as)
  150.     char *as;
  151. {
  152.     register char *cs;
  153.     register char *sgpathp, *oldcs;
  154.     struct stat stb;
  155.  
  156.     sgpathp = gpathp;
  157.     cs = as;
  158.     if (*cs == '~' && gpathp == gpath) {
  159.         addpath('~');
  160.         for (cs++; letter(*cs) || digit(*cs) || *cs == '-';)
  161.             addpath(*cs++);
  162.         if (!*cs || *cs == '/') {
  163.             if (gpathp != gpath + 1) {
  164.                 *gpathp = 0;
  165.                 globerr = "Unknown user name after ~";
  166.                 (void) strcpy(gpath, gpath + 1);
  167.             } else
  168.                 {
  169.                 sprintf(gpath,"user:%s",home);
  170.                 /* (void) strcpy(gpath, home); */
  171.                 }
  172.             gpathp = strend(gpath);
  173.         }
  174.     }
  175.     while (!any(*cs, globchars)) {
  176.         if (*cs == 0) {
  177.             if (!globbed)
  178.                 Gcat(gpath, "");
  179.             else if (stat(gpath, &stb) >= 0) {
  180.                 Gcat(gpath, "");
  181.                 globcnt++;
  182.             }
  183.             goto endit;
  184.         }
  185.         addpath(*cs++);
  186.     }
  187.     oldcs = cs;
  188.     while (cs > as && *cs != '/')
  189.         cs--, gpathp--;
  190.     if (*cs == '/')
  191.         cs++, gpathp++;
  192.     *gpathp = 0;
  193.     if (*oldcs == '{') {
  194.         (void) execbrc(cs, ((char *)0));
  195.         return;
  196.     }
  197.     matchdir(cs);
  198. endit:
  199.     gpathp = sgpathp;
  200.     *gpathp = 0;
  201. }
  202.  
  203. static
  204. matchdir(pattern)
  205.     char *pattern;
  206. {
  207. #if 0
  208.     struct stat stb;
  209.     register struct direct *dp;
  210.     DIR *dirp;
  211.  
  212.     dirp = opendir(gpath);
  213.     if (dirp == NULL) {
  214.         if (globbed)
  215.             return;
  216.         goto patherr2;
  217.     }
  218.     if (fstat(dirp->dd_fd, &stb) < 0)
  219.         goto patherr1;
  220.     if (!isdir(stb)) {
  221.         errno = ENOTDIR;
  222.         goto patherr1;
  223.     }
  224.     while ((dp = readdir(dirp)) != NULL) {
  225.         if (dp->d_ino == 0)
  226.             continue;
  227.         if (match(dp->d_name, pattern)) {
  228.             Gcat(gpath, dp->d_name);
  229.             globcnt++;
  230.         }
  231.     }
  232.     closedir(dirp);
  233.     return;
  234.  
  235. patherr1:
  236.     closedir(dirp);
  237. patherr2:
  238.     globerr = "Bad directory components";
  239. #endif
  240. }
  241.  
  242. static
  243. execbrc(p, s)
  244.     char *p, *s;
  245. {
  246.     char restbuf[BUFSIZ + 2];
  247.     register char *pe, *pm, *pl;
  248.     int brclev = 0;
  249.     char *lm, savec, *sgpathp;
  250.  
  251.     for (lm = restbuf; *p != '{'; *lm++ = *p++)
  252.         continue;
  253.     for (pe = ++p; *pe; pe++)
  254.     switch (*pe) {
  255.  
  256.     case '{':
  257.         brclev++;
  258.         continue;
  259.  
  260.     case '}':
  261.         if (brclev == 0)
  262.             goto pend;
  263.         brclev--;
  264.         continue;
  265.  
  266.     case '[':
  267.         for (pe++; *pe && *pe != ']'; pe++)
  268.             continue;
  269.         continue;
  270.     }
  271. pend:
  272.     brclev = 0;
  273.     for (pl = pm = p; pm <= pe; pm++)
  274.     switch (*pm & (QUOTE|TRIM)) {
  275.  
  276.     case '{':
  277.         brclev++;
  278.         continue;
  279.  
  280.     case '}':
  281.         if (brclev) {
  282.             brclev--;
  283.             continue;
  284.         }
  285.         goto doit;
  286.  
  287.     case ','|QUOTE:
  288.     case ',':
  289.         if (brclev)
  290.             continue;
  291. doit:
  292.         savec = *pm;
  293.         *pm = 0;
  294.         (void) strcpy(lm, pl);
  295.         (void) strcat(restbuf, pe + 1);
  296.         *pm = savec;
  297.         if (s == 0) {
  298.             sgpathp = gpathp;
  299.             expand(restbuf);
  300.             gpathp = sgpathp;
  301.             *gpathp = 0;
  302.         } else if (amatch(s, restbuf))
  303.             return (1);
  304.         sort();
  305.         pl = pm + 1;
  306.         if (brclev)
  307.             return (0);
  308.         continue;
  309.  
  310.     case '[':
  311.         for (pm++; *pm && *pm != ']'; pm++)
  312.             continue;
  313.         if (!*pm)
  314.             pm--;
  315.         continue;
  316.     }
  317.     if (brclev)
  318.         goto doit;
  319.     return (0);
  320. }
  321.  
  322. static
  323. match(s, p)
  324.     char *s, *p;
  325. {
  326.     register int c;
  327.     register char *sentp;
  328.     char sglobbed = globbed;
  329.  
  330.     if (*s == '.' && *p != '.')
  331.         return (0);
  332.     sentp = entp;
  333.     entp = s;
  334.     c = amatch(s, p);
  335.     entp = sentp;
  336.     globbed = sglobbed;
  337.     return (c);
  338. }
  339.  
  340. static
  341. amatch(s, p)
  342.     register char *s, *p;
  343. {
  344. #if 0
  345.     register int scc;
  346.     int ok, lc;
  347.     char *sgpathp;
  348.     struct stat stb;
  349.     int c, cc;
  350.  
  351.     globbed = 1;
  352.     for (;;) {
  353.         scc = *s++ & TRIM;
  354.         switch (c = *p++) {
  355.  
  356.         case '{':
  357.             return (execbrc(p - 1, s - 1));
  358.  
  359.         case '[':
  360.             ok = 0;
  361.             lc = 077777;
  362.             while (cc = *p++) {
  363.                 if (cc == ']') {
  364.                     if (ok)
  365.                         break;
  366.                     return (0);
  367.                 }
  368.                 if (cc == '-') {
  369.                     if (lc <= scc && scc <= *p++)
  370.                         ok++;
  371.                 } else
  372.                     if (scc == (lc = cc))
  373.                         ok++;
  374.             }
  375.             if (cc == 0)
  376.                 if (ok)
  377.                     p--;
  378.                 else
  379.                     return 0;
  380.             continue;
  381.  
  382.         case '*':
  383.             if (!*p)
  384.                 return (1);
  385.             if (*p == '/') {
  386.                 p++;
  387.                 goto slash;
  388.             }
  389.             s--;
  390.             do {
  391.                 if (amatch(s, p))
  392.                     return (1);
  393.             } while (*s++);
  394.             return (0);
  395.  
  396.         case 0:
  397.             return (scc == 0);
  398.  
  399.         default:
  400.             if (c != scc)
  401.                 return (0);
  402.             continue;
  403.  
  404.         case '?':
  405.             if (scc == 0)
  406.                 return (0);
  407.             continue;
  408.  
  409.         case '/':
  410.             if (scc)
  411.                 return (0);
  412. slash:
  413.             s = entp;
  414.             sgpathp = gpathp;
  415.             while (*s)
  416.                 addpath(*s++);
  417.             addpath('/');
  418.             if (stat(gpath, &stb) == 0 && isdir(stb))
  419.                 if (*p == 0) {
  420.                     Gcat(gpath, "");
  421.                     globcnt++;
  422.                 } else
  423.                     expand(p);
  424.             gpathp = sgpathp;
  425.             *gpathp = 0;
  426.             return (0);
  427.         }
  428.     }
  429. #else
  430.     return 0;
  431. #endif
  432. }
  433.  
  434. static
  435. Gmatch(s, p)
  436.     register char *s, *p;
  437. {
  438.     register int scc;
  439.     int ok, lc;
  440.     int c, cc;
  441.  
  442.     for (;;) {
  443.         scc = *s++ & TRIM;
  444.         switch (c = *p++) {
  445.  
  446.         case '[':
  447.             ok = 0;
  448.             lc = 077777;
  449.             while (cc = *p++) {
  450.                 if (cc == ']') {
  451.                     if (ok)
  452.                         break;
  453.                     return (0);
  454.                 }
  455.                 if (cc == '-') {
  456.                     if (lc <= scc && scc <= *p++)
  457.                         ok++;
  458.                 } else
  459.                     if (scc == (lc = cc))
  460.                         ok++;
  461.             }
  462.             if (cc == 0)
  463.                 if (ok)
  464.                     p--;
  465.                 else
  466.                     return 0;
  467.             continue;
  468.  
  469.         case '*':
  470.             if (!*p)
  471.                 return (1);
  472.             for (s--; *s; s++)
  473.                 if (Gmatch(s, p))
  474.                     return (1);
  475.             return (0);
  476.  
  477.         case 0:
  478.             return (scc == 0);
  479.  
  480.         default:
  481.             if ((c & TRIM) != scc)
  482.                 return (0);
  483.             continue;
  484.  
  485.         case '?':
  486.             if (scc == 0)
  487.                 return (0);
  488.             continue;
  489.  
  490.         }
  491.     }
  492. }
  493.  
  494. static
  495. Gcat(s1, s2)
  496.     register char *s1, *s2;
  497. {
  498.     register int len = strlen(s1) + strlen(s2) + 1;
  499.  
  500.     if (len >= gnleft || gargc >= GAVSIZ - 1)
  501.         globerr = "Arguments too long";
  502.     else {
  503.         gargc++;
  504.         gnleft -= len;
  505.         gargv[gargc] = 0;
  506.         gargv[gargc - 1] = strspl(s1, s2);
  507.     }
  508. }
  509.  
  510. static
  511. addpath(c)
  512.     char c;
  513. {
  514.  
  515.     if (gpathp >= lastgpathp)
  516.         globerr = "Pathname too long";
  517.     else {
  518.         *gpathp++ = c;
  519.         *gpathp = 0;
  520.     }
  521. }
  522.  
  523. static
  524. rscan(t, f)
  525.     register char **t;
  526.     int (*f)();
  527. {
  528.     register char *p, c;
  529.  
  530.     while (p = *t++) {
  531.         if (f == tglob)
  532.             if (*p == '~')
  533.                 gflag |= 2;
  534.             else if (eq(p, "{") || eq(p, "{}"))
  535.                 continue;
  536.         while (c = *p++)
  537.             (*f)(c);
  538.     }
  539. }
  540. /*
  541. static
  542. scan(t, f)
  543.     register char **t;
  544.     int (*f)();
  545. {
  546.     register char *p, c;
  547.  
  548.     while (p = *t++)
  549.         while (c = *p)
  550.             *p++ = (*f)(c);
  551. } */
  552.  
  553. static
  554. tglob(c)
  555.     register char c;
  556. {
  557.  
  558.     if (any(c, globchars))
  559.         gflag |= c == '{' ? 2 : 1;
  560.     return (c);
  561. }
  562. /*
  563. static
  564. trim(c)
  565.     char c;
  566. {
  567.  
  568.     return (c & TRIM);
  569. } */
  570.  
  571.  
  572. letter(c)
  573.     register char c;
  574. {
  575.  
  576.     return (c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z' || c == '_');
  577. }
  578.  
  579. digit(c)
  580.     register char c;
  581. {
  582.  
  583.     return (c >= '0' && c <= '9');
  584. }
  585.  
  586. any(c, s)
  587.     register int c;
  588.     register char *s;
  589. {
  590.  
  591.     while (*s)
  592.         if (*s++ == c)
  593.             return(1);
  594.     return(0);
  595. }
  596. blklen(av)
  597.     register char **av;
  598. {
  599.     register int i = 0;
  600.  
  601.     while (*av++)
  602.         i++;
  603.     return (i);
  604. }
  605.  
  606. char **
  607. blkcpy(oav, bv)
  608.     char **oav;
  609.     register char **bv;
  610. {
  611.     register char **av = oav;
  612.  
  613.     while (*av++ = *bv++)
  614.         continue;
  615.     return (oav);
  616. }
  617.  
  618. blkfree(av0)
  619.     char **av0;
  620. {
  621.     register char **av = av0;
  622.  
  623.     while (*av)
  624.         free(*av++);
  625. }
  626.  
  627. static
  628. char *
  629. strspl(cp, dp)
  630.     register char *cp, *dp;
  631. {
  632.     register char *ep = malloc((unsigned)(strlen(cp) + strlen(dp) + 1));
  633.  
  634.     if (ep == (char *)0)
  635.         fatal("Out of memory");
  636.     (void) strcpy(ep, cp);
  637.     (void) strcat(ep, dp);
  638.     return (ep);
  639. }
  640.  
  641. char **
  642. copyblk(v)
  643.     register char **v;
  644. {
  645.     register char **nv = (char **)malloc((unsigned)((blklen(v) + 1) *
  646.                         sizeof(char **)));
  647.     if (nv == (char **)0)
  648.         fatal("Out of memory");
  649.  
  650.     return (blkcpy(nv, v));
  651. }
  652.  
  653. static
  654. char *
  655. strend(cp)
  656.     register char *cp;
  657. {
  658.  
  659.     while (*cp)
  660.         cp++;
  661.     return (cp);
  662. }
  663.